<?php
class CAttachment {
	//允许上传类型
	private $alowexts;
	//最大上传大小
	private $maxsize;
	//上传路径
	private $upload_root;
	//错误
	private $error;
	
	function __construct($upload_dir = ''){
		$this->alowexts = RonBase::load_config('system','file_exts');
		$this->maxsize = RonBase::load_config('system','file_size');
		$this->upload_root = RonBase::load_config('system','upload_path');
	}
	
	/**
	 * 上传
	 *是否覆盖原有文件$overwrite
	UPLOAD_ERR_OK */
	public function upload($field,$overwrite,$upload_dir){
		if(!isset($_FILES[$field])){
			$this->error = 14;
			return false;
		}
		$savepath = $this->upload_root.$upload_dir.DIRECTORY_SEPARATOR;
		if($_FILES[$field]['error'] != UPLOAD_ERR_OK){
			$this->error = $_FILES[$field]['error'];
			return false;
		} else{
			$file = array('tmp_name' => $_FILES[$field]['tmp_name'], 'name' => $_FILES[$field]['name'], 'type' => $_FILES[$field]['type'], 'size' => $_FILES[$field]['size'] );
			if(!$this->dir_create($savepath)) {
			$this->error = '8';
			return false;
			}
			if(!is_dir($savepath)) {
				$this->error = '8';
				return false;
			}
			@chmod($savepath, 0777);
			if(!is_writeable($savepath)) {
				$this->error = '9';
				return false;
			}
			$fileext = $this->fileext($file['name']);			
			if(!in_array($fileext,$this->alowexts)){
				$this->error = '10';
				return false;
			}
			if($this->maxsize && $file['size'] > $this->maxsize) {
				$this->error = '11';
				return false;
			}
			if(!$this->isuploadedfile($file['tmp_name'])) {
				$this->error = '12';
				return false;
			}
			$temp_filename = $this->getname($fileext);			
			$savefile = $savepath.$temp_filename;
			$savefile = preg_replace("/(php|phtml|php3|php4|jsp|exe|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i", "_\\1\\2", $savefile);
			$request = new SlashesValidator();
			$filepath = preg_replace($request->new_addslashes("|^".$this->upload_root."|"), "", $savefile);
			if(!$overwrite && file_exists($savefile)) continue;
			if(@copy($file['tmp_name'], $savefile)) {
				@chmod($savefile, 0644);
				@unlink($file['tmp_name']);
				$uploadedfile = array('filename'=>$file['name'], 'filepath'=>$filepath, 'filesize'=>$file['size'], 'fileext'=>$fileext);
				$aid=$this->add($uploadedfile);
			}
			return $aid;
		}		
	}
	
	/**
	 * 参数处理并下载
	 */
	public function download(){
		$a_k = $_GET['a_k'];
		$auth_key = md5(RonBase::load_config('system','auth_key'));
		$process = new CProcess();
		$a_k = $process->sys_auth($a_k, 'DECODE', $auth_key);
		if(empty($a_k)) CAdmin::showmessage('参数错误');
		unset($f,$t,$ip);
		parse_str($a_k);
		$request = new SlashesValidator();
		$f = $request->new_stripslashes($f);
		if(!isset($t)) CAdmin::showmessage('参数错误');
		if(!isset($ip)) CAdmin::showmessage('参数错误');
		if(empty($f)) CAdmin::showmessage('下载地址无效');
		$starttime = intval($t);
		$endtime = SYS_TIME - $starttime;
		if($endtime > 3600)  CAdmin::showmessage('下载地址已过期');
		if(preg_match('/(php|phtml|php3|php4|jsp|dll|asp|cer|asa|shtml|shtm|aspx|asax|cgi|fcgi|pl)(\.|$)/i',$f) || strpos($f,':\\') !==false || strpos($f,'..')!==false)CAdmin::showmessage('下载地址无效');
		$fileurl = trim($f);
		$sysfunction = new CSysfunction();
		if(empty($fileurl) || !preg_match('/[0-9]{10}/', $starttime) || !preg_match('/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/', $ip) || $ip!=$sysfunction->get_ip()) CAdmin::showmessage('参数错误');
		$fileurl = $this->upload_root.$fileurl;
		$filename = basename($fileurl);
		$ext = $this->fileext($filename);
		$filename = date('Ymd_his').rand(1, 99).'.'.$ext;//防止知道真正文件名
		$this->file_down($fileurl,$filename);
	}
	
	/**
	 * 附件信息存入数据库
	 */
	private function add($uploadedfile){
		$att_db = new Attachment_Model();
		$uploadedfile['uploadtime'] = SYS_TIME;
		$system = new CSysfunction();
		$uploadedfile['uploadip'] = $system->get_ip();
		$request = new SlashesValidator();
		$uploadedfile = $request->new_addslashes($uploadedfile);
		$att_db->insert($uploadedfile);
		$aid = $att_db->insert_id();
		return $aid;		
	}
	
	/**
	 * 文件下载
	 */
	private function file_down($filepath,$filename = ''){
		if(!$filename) $filename = basename($filepath);
		$sysfunction = new CSysfunction();
		if($sysfunction->is_ie()) $filename = rawurlencode($filename);
		$filetype = $this->fileext($filename);
		$filesize = sprintf('%u',filesize($filepath));
		if(ob_get_length() !== false) @ob_end_clean();
		header('Pragma: public');
		header('Last-Modified: '.gmdate('D, d M Y H:i:s') . 'GMT');
		header('Cache-Control: no-store, no-cache, must-revalidate');
		header('Cache-Control: pre-check=0, post-check=0, max-age=0');	
		header('Content-Transfer-Encoding: binary');
		header('Content-Encoding: none');	
		header('Content-type: '.$filetype);
		header('Content-Disposition: attachment; filename="'.$filename.'"');
		header('Content-length: '.$filesize);
		readfile($filepath);
		exit;
	}
	
	/**
	 * 文件删除
	 */
	public function delete($where){
		$att_db = new Attachment_Model();
		$result = $att_db->select($where);
		foreach($result as $r) {
			$filepath = $this->upload_root.$r['filepath'];
			@unlink($filepath);
		}		
		$att_db->delete($where);
		return true;
	}
	
	public function delete_all($dirName){
		//删除数据
		$att_db = new Attachment_Model();
		$att_index_db = new Attachment_index_Model();
		$att_indexs = $att_index_db->select(array('contract_num'=>$dirName),'aid');
		foreach ($att_indexs as $att_index) {
			$att_db->delete(array('aid'=>$att_index['aid']));
		}
		$att_index_db->delete(array('contract_num'=>$dirName));
		//删除附件
		$dirName = $this->upload_root.$dirName;
		if ($handle = @opendir($dirName)) {		
			while (false !== ($item = readdir($handle) ) ) {
				if ( $item != "." && $item != ".." ) {
					@unlink($dirName.DIRECTORY_SEPARATOR.$item);
				}
			}
			 closedir($handle);
			 @rmdir($dirName);
		}
	}
	
	/**
	 * 返回错误信息
	 */
	public function error() {
		$UPLOAD_ERROR = array(
		0 => '文件上传成功',
		1 => '上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值',
		2 => '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
		3 => '文件只有部分被上传',
		4 => '没有文件被上传',
		5 => '服务器临时文件夹丢失',
		6 => '找不到临时文件夹',
		7 => '文件写入临时文件夹失败',
		8 => '附件目录创建不成功',
		9 => '附件目录没有写入权限',
		10 => '不允许上传该类型文件',
		11 => '文件超过了管理员限定的大小',
		12 => '非法上传文件',
		13 => '24小时内上传附件个数超出了系统限制',
		14 => '没有上传文件',
		);		
		return $UPLOAD_ERROR[$this->error];
	}
	
	/**
	 * 下载地址
	 */
	public function get_downurl($url){
		$auth_key = md5(RonBase::load_config('system','auth_key'));
		$process = new CProcess();
		$sysfunction = new CSysfunction();
		//从时间和ip上加密，防止盗链
		$a_k = urlencode($process->sys_auth("t=".SYS_TIME."&ip=".$sysfunction->get_ip()."&f=$url", 'ENCODE', $auth_key));
		return $a_k;
	}
	
	/**
	 * 创建目录
	 */
	private function dir_create($path){
		if(is_dir($path)) return true;
		$path = $this->dir_path($path);
		$temp = explode('/',$path);
		$max = count($temp) - 1;
		$cur_dir = '';
		for($i = 0; $i < $max; $i++){
			$cur_dir .= $temp[$i].'/';
			if(@is_dir($cur_dir)) continue;
			@mkdir($cur_dir,0777,true);
			@chmod($cur_dir,0777);
		}
		return is_dir($path);
	}
	/**
	* 转化 \ 为 /
	* 
	* @param	string	$path	路径
	* @return	string	路径
	*/
	private function dir_path($path){
		$path = str_replace('\\', '/', $path);
		if(substr($path,-1) != '/') $path = $path.'/';
		return $path;
	}
	
	/**
	 * 取得文件扩展名
	 */
	private function fileext($filename){
		return strtolower(trim(substr(strrchr($filename, '.'), 1, 10)));
	}
	
	/**
	 * 判断是否通过post上传
	 */
	private function isuploadedfile($file){
		return is_uploaded_file($file);
	}
	
	/**
	 * 获取附件名称
	 * @param $fileext 附件扩展名
	 */
	private function getname($fileext){
		return date('Ymdhis').rand(100, 999).'.'.$fileext;
	}	

}